package com.example.points.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.points.domain.UserPoints;
import com.example.points.domain.PointsDetail;
import com.example.points.domain.PointsOperationLog;
import com.example.points.mapper.UserPointsMapper;
import com.example.points.mapper.PointsDetailMapper;
import com.example.points.mapper.PointsOperationLogMapper;
import com.example.points.service.PointsService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class PointsServiceImpl implements PointsService {
    private final UserPointsMapper userPointsMapper;
    private final PointsDetailMapper pointsDetailMapper;
    private final PointsOperationLogMapper operationLogMapper;
    private final RedisTemplate<String, Object> redisTemplate;

    private static final String POINTS_CACHE_KEY = "user:points:";
    private static final long CACHE_EXPIRE_TIME = 30;

    @Override
    public UserPoints queryUserPoints(Long userId) {
        String cacheKey = POINTS_CACHE_KEY + userId;
        UserPoints userPoints = (UserPoints) redisTemplate.opsForValue().get(cacheKey);
        
        if (userPoints == null) {
            userPoints = userPointsMapper.selectOne(
                new LambdaQueryWrapper<UserPoints>()
                    .eq(UserPoints::getUserId, userId)
            );
            if (userPoints != null) {
                redisTemplate.opsForValue().set(cacheKey, userPoints, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
            }
        }
        
        return userPoints;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rechargePoints(Long userId, Long points) {
        UserPoints userPoints = queryUserPoints(userId);
        if (userPoints == null) {
            userPoints = new UserPoints();
            userPoints.setUserId(userId);
            userPoints.setTotalPoints(points);
            userPoints.setAvailablePoints(points);
            userPointsMapper.insert(userPoints);
        } else {
            userPoints.setTotalPoints(userPoints.getTotalPoints() + points);
            userPoints.setAvailablePoints(userPoints.getAvailablePoints() + points);
            userPointsMapper.updateById(userPoints);
        }

        // 记录积分明细
        PointsDetail detail = new PointsDetail();
        detail.setUserId(userId);
        detail.setPoints(points);
        detail.setType(1); // 充值
        detail.setStatus(1);
        detail.setExpireTime(LocalDateTime.now().plusYears(1));
        pointsDetailMapper.insert(detail);

        // 记录操作日志
        PointsOperationLog log = new PointsOperationLog();
        log.setUserId(userId);
        log.setPoints(points);
        log.setOperationType(1);
        log.setOperationDesc("积分充值");
        operationLogMapper.insert(log);

        // 更新缓存
        redisTemplate.delete(POINTS_CACHE_KEY + userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean consumePoints(Long userId, Long points) {
        UserPoints userPoints = queryUserPoints(userId);
        if (userPoints == null || userPoints.getAvailablePoints() < points) {
            return false;
        }

        userPoints.setAvailablePoints(userPoints.getAvailablePoints() - points);
        userPointsMapper.updateById(userPoints);

        // 记录积分明细
        PointsDetail detail = new PointsDetail();
        detail.setUserId(userId);
        detail.setPoints(-points);
        detail.setType(2); // 消费
        detail.setStatus(1);
        pointsDetailMapper.insert(detail);

        // 记录操作日志
        PointsOperationLog log = new PointsOperationLog();
        log.setUserId(userId);
        log.setPoints(-points);
        log.setOperationType(2);
        log.setOperationDesc("积分消费");
        operationLogMapper.insert(log);

        // 更新缓存
        redisTemplate.delete(POINTS_CACHE_KEY + userId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchRechargePoints(List<Long> userIds, Long points) {
        for (Long userId : userIds) {
            rechargePoints(userId, points);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchConsumePoints(List<Long> userIds, Long points) {
        for (Long userId : userIds) {
            consumePoints(userId, points);
        }
    }

    @Override
    public List<PointsOperationLog> queryOperationLogs(Long userId, Integer operationType, String startTime, String endTime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime start = LocalDateTime.parse(startTime, formatter);
        LocalDateTime end = LocalDateTime.parse(endTime, formatter);

        return operationLogMapper.selectList(
            new LambdaQueryWrapper<PointsOperationLog>()
                .eq(userId != null, PointsOperationLog::getUserId, userId)
                .eq(operationType != null, PointsOperationLog::getOperationType, operationType)
                .between(PointsOperationLog::getCreatedTime, start, end)
                .orderByDesc(PointsOperationLog::getCreatedTime)
        );
    }
} 